package com.kingsoft.dc.khaos.module.spark.model.TechCheck;

import com.kingsoft.dc.khaos.module.spark.util.DateTimeForamtUtil;
import lombok.val;
import org.apache.commons.lang3.StringUtils;


import java.io.Serializable;
import java.util.List;
import java.util.regex.Pattern;

public abstract class KsyunCheckRule implements Serializable{
    private static final String IntPattern  =  "^[1-9]+[0-9]*n";
    private static final String FloatPattern  =  "^[1-9]+[0-9]*n\\([1-9]+[0-9]*\\)";

    /**
     *  !  表示定长
     *  .. 表示不定长
     *  a 表示字母
     *  c 表示汉子
     *  n 表示数字
     *  pn(s) 表示浮点型
     *
     * @param dataType
     */
    public static KsyunCheckRule ddlDataTypeParse(String dataType, int isfixedlength) {
        //判断数据类型 字符串  数字  日期 三大类
        String spliter= null;
        if(dataType.equals("CLOB") || dataType.equals("BLOB") ){  //大对象 clob blob
            val lenth = 0;
            val dtype = dataType;
            return new KsyunLobCheckRule(dataType);
        }else if(dataType.indexOf("!")>0){  // 定长字符串 ： k!n  k!a  k!an
            val strs = dataType.split("!");
            val lenth = Integer.parseInt(strs[0]);
            val dtype = strs[1];
            return new KsyunStringCheckRule(dataType,lenth,dtype,true  );
        }else if(dataType.indexOf("..")>0){   //变长字符串： n..k   nc..k
            val strs = dataType.split("\\.\\.");
            val lenth = Integer.parseInt(strs[1]);
            val dtype = strs[0];
            return new KsyunStringCheckRule(dataType,lenth,dtype,isfixedlength == 1  );  //如果字段类型费定长，还要判断是否ddl中的 isfixedlength 是否为定长
        }else{
            //数值型解析  kn   pn(s)
            if(Pattern.matches(IntPattern, dataType)){   // 整数类型
                val dtype = "n";
                val length = dataType.substring(0,dataType.length()-1);
                return new KsyunNumberCheckRule(dataType,Integer.parseInt(length),0,isfixedlength==1);
            }else if(Pattern.matches(FloatPattern, dataType)){   // 浮点数类型
                val dtype = "n";
                val strs = dataType.split("n");
                val length = strs[0];
                val decimalLength = strs[1].substring(1,strs[1].length()-1) ;// 小数位
                return new KsyunNumberCheckRule(dataType,Integer.parseInt(length),Integer.parseInt(decimalLength),isfixedlength==1);
            }else if(DateTimeForamtUtil.checkFormaterExist(dataType)){  // 日期/时间型解析  判断格式是否合法
                //日期格式数据
                return new KsyunDatetimeCheckRule(dataType);
            }else{    // 数据类型无法解析，抛出异常
                throw new RuntimeException("数据类型:"+ dataType + " 无法解析，请检查ddl文件是否符合规范");
            }
        }
    }

    /**
     * check方法逻辑修改：
     *  检核通过返回null
     *  检核告警返回告警信息和告警
     *  检核rejuect 抛出异常
     * @param value
     * @return
     * @throws RuntimeException
     */
    public abstract Tuple4<String,String, KsyunErrorCode,String> check(String value) throws RuntimeException ;

    //主键非空检查
    public static void keyCheck(List<KeyInfo> keys , String[] cols){
        for(KeyInfo key:keys ){
            if(StringUtils.isBlank(cols[key.index]))
                throw new KsyunTechCheckException(KsyunErrorCode.KEY_CHEKC,"空字段:"+ key.fieldname );
        }
    }
}
